﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;

namespace XPathAutoSuggest {
    /// <summary>Interface dictates what members are required to be a viable XPath Utility</summary>
    /// <remarks>Coding against interfaces provides many benefits, in this case, one specific benefit is improved testability</remarks>
    public interface IXPathUtility {
        /// <summary>
        /// Gets suggested XPath queries
        /// </summary>
        /// <param name="allXml">The complete XML document</param>
        /// <param name="selectedText">The text which should be selected by the queries returned</param>
        /// <param name="selectionStart">Position where of the tag/node we need a query for</param>
        /// <returns>A collection of queries with descriptinons</returns>
        ObservableCollection<QueryDescPair> GetXPathQueries(string allXml,
                                string selectedText, int selectionStart);

        /// <summary>
        /// Returns a simple path when given XML, selected text and selection start
        /// </summary>
        /// <param name="allXml">Contains caller's selection</param>
        /// <param name="selectedText">Text caller wants path for</param>
        /// <param name="selectionStart">Numeric index used for non-unique selections</param>
        /// <param name="tagName">Out, if populated, the tag name selected by user</param>
        /// <param name="indexedPath">(out) An XPath query with indexing to distinguish between otherwise similar
        /// paths, such as /country/states[16]; the output may be empty if not necessary</param>
        /// <param name="nodeVal">If user select a node of substring, will receive the full node text</param>
        /// <returns>A string like 'Bookstore/book/title'</returns>
        /// <remarks>This overloaded version is used when </remarks>
        string GetNodePath(string allXml, string selectedText, int selectionStart,
                                out string tagName, out string indexedPath,
                                out string nodeVal);
        
        /// <summary>
        /// If user searches for a node that has peers, it causes problems when generating
        /// the path using the nodePathCounts, remove them here
        /// </summary>
        /// <param name="nodePathCounts">Contains counts of every path encountered so far</param>
        /// <param name="tagStack">Every tag we have encounterd so far, excluding irrelevant paths</param>
        void RemoveMoreSpecificPaths(Dictionary<string, int> nodePathCounts, Stack<XmlHelperNode> tagStack);

        /// <summary>
        /// Returns the name of the tag we are currently on as indicated by p
        /// </summary>
        /// <param name="allXml">The XML we are working with</param>
        /// <param name="selPos">Position of users' tag/node</param>
        /// <param name="p">Where our 'pointer' currently is parsing the XML</param>
        /// <param name="nodeStart">Start of the tag we are in</param>
        /// <returns>A node name</returns>
        string GetTagName(string allXml, int selPos, int p, int nodeStart);

        /// <summary>
        /// Returns the entire node given an index to a point inside the node
        /// </summary>
        /// <param name="allXml">The XML containing the node in question</param>
        /// <param name="selectionStart">Index to a position within the node</param>
        /// <returns>The node text</returns>
        string GetNodeVal(string allXml, int selectionStart);

        /// <summary>
        /// Checks the xml and returns an error if there is a problem
        /// </summary>
        /// <param name="xml">Some xml that might not be valid</param>
        /// <returns>Empty string or else an error message</returns>
        string ValidateXml(string xml);
        
        /// <summary>
        /// Gets the node at the specified position p within allXml, updating tagStart to after the node
        /// </summary>
        /// <param name="allXml">The XML text to seek a tag within</param>
        /// <param name="aNode">Text of the node that will be returned</param>
        /// <param name="p">( ref) Position within the text where we start seeking, will be incremented</param>
        /// <param name="tagStart">(ref) Position of our hit</param>
        void GetNode(string allXml, out XmlHelperNode aNode, ref int p, ref int tagStart);

        /// <summary>
        /// Gets the number of nodes within allXml that are matched by the specified path
        /// </summary>
        /// <param name="allXMl">The XML containing nodes with peers</param>
        /// <param name="path">XPath query to one of the nodes who might have peers</param>
        /// <returns>Count</returns>
        int GetPeerCount(string allXMl, string path);
    }
}
